package com.inspinia.base.dao.config;

import com.alibaba.druid.filter.logging.Slf4jLogFilter;
import com.inspinia.base.dao.db.DataSources;
import com.inspinia.base.dao.db.ThreadLocalRoutingDataSource;
import com.inspinia.base.dao.pageable.MybatisPageableInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.support.TransactionTemplate;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Map;
import java.util.Properties;


@org.springframework.context.annotation.Configuration
@EnableTransactionManagement(proxyTargetClass = true, order = 0)
public class DataSourceConfig {

    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    static ThreadLocalRoutingDataSource localRoutingDataSource;

    @Bean(name = "dataSource")
    public static DataSource ThreadLocalRoutingDataSource() {
        if (localRoutingDataSource == null) {
            localRoutingDataSource = new ThreadLocalRoutingDataSource();
            Map<Object, Object> dataSources = DataSourceUtil.getDataSources();
            localRoutingDataSource.setTargetDataSources(dataSources);
            localRoutingDataSource.setDefaultTargetDataSource(dataSources.get(DataSources.MASTER));
            localRoutingDataSource.afterPropertiesSet();
        }
        return localRoutingDataSource;
    }

    @Bean
    public static Slf4jLogFilter slf4jLogFilter() {
        Slf4jLogFilter slf4jLogFilter = new Slf4jLogFilter();
        slf4jLogFilter.setDataSourceLogEnabled(false);
        slf4jLogFilter.setConnectionLogEnabled(false);
        slf4jLogFilter.setResultSetLogEnabled(false);
        slf4jLogFilter.setStatementLogEnabled(false);
        slf4jLogFilter.setStatementExecutableSqlLogEnable(true);
        return slf4jLogFilter;
    }

    /*mybatis-service*/
    @Bean(name = "sqlSessionFactory")
    public static SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(ThreadLocalRoutingDataSource());
        sqlSessionFactoryBean.setConfiguration(configuration());
        MybatisPageableInterceptor mybatisPageableInterceptor = new MybatisPageableInterceptor();
        Properties p = new Properties();
        p.setProperty("dialectClass","com.inspinia.base.dao.pageable.MySQLDialect");
        mybatisPageableInterceptor.setProperties(p);
        Interceptor[] interceptors = {mybatisPageableInterceptor};
        sqlSessionFactoryBean.setPlugins(interceptors);
        return sqlSessionFactoryBean.getObject();
    }

    @Bean(name = "sqlSessionTemplate")
    public static SqlSessionTemplate sqlSessionTemplate() throws Exception {
        SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory());
        return sqlSessionTemplate;
    }

    @Bean
    public static Configuration configuration(){
        Configuration configuration = new Configuration();
        configuration.setCacheEnabled(true);
        configuration.setUseGeneratedKeys(true);
        configuration.setMapUnderscoreToCamelCase(true);
        return configuration;
    }

    /*mybatis transactionManager*/
    @Bean(name = "transactionManager")
    public static DataSourceTransactionManager transactionManager() throws SQLException {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(ThreadLocalRoutingDataSource());
        return dataSourceTransactionManager;
    }

    @Bean(name = "transactionTemplate")
    public static TransactionTemplate transactionTemplate() throws SQLException {
        TransactionTemplate transactionTemplate = new TransactionTemplate();
        transactionTemplate.setTransactionManager(transactionManager());
        return transactionTemplate;
    }

    @Bean
    public static MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setBasePackage("com.inspinia.**.mapper,com.inspinia.**.dao");
        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
        return mapperScannerConfigurer ;
    }
}
